-
-
Notifications
You must be signed in to change notification settings - Fork 80
USB stdio #332
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
USB stdio #332
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
The pbsys_host layer was intended to combine all stdio through a single interface. However, this does not allow users to specify where stdout goes or which input source data came from. For example, they may want to print debug messages over Bluetooth while communicating with another device over USB. Instead, we will create separate stdio interfaces for each connection type so that users can choose which to use if they want to.
It is possible for print functions to raise an exception, so we need to catch this when printing a final exception since the nlr stack is empty at that point and would otherwise cause a crash.
Add a new function to convert PBIO error codes to MicroPython errnos. This works similar to pb_assert(), but does not raise an exception. There are some cases where we need to convert PBIO errors to errnos without raising an exception, such as when implementing the stream protocol.
Add a new stream object that uses the Pybricks Profile stdin/stdout over Bluetooth. This is available a hub.bluetooth.io and can be used to send and receive data over Bluetooth even when something else is used for sys.stdin/stdout (e.g. USB).
Pull in changes to allow mutable sys.stdin, sys.stdout, and sys.stderr.
Change the sys.stdin, sys.stdout, and sys.stderr objects to be mutable so that they can be replaced with USB stdio when available on hubs that support it.
Add transport parameter to pbsys_command() so that it can distinguish between commands received over USB and Bluetooth.
Copy the ring buffer logic from bluetooth to usb_stm32.c so that we can get stdin commands over USB working.
Add a new USB stream type that can be used for stdin, stdout, and stderr over USB. For now, this just lives at hub.usb.io.
Implement the Pybricks Profile event subscription flag. This saves us from trying to send messages to the host when there is no app running to receive them. Previously, trying to write to stdout would block forever because of this. The 5 millisecond timeout is arbitrary. Wireshark shows that the OUT endpoint is being serviced in less than 1 ms, so this should be plenty of time even if some hosts are an order of magnitude slower. We don't want to make it too big because it will delay user programs for this long and we don't want to mess up someone's control loop too badly.
Pass the transport type that requested the user program to start to the MicroPython launcher to allow it to select the appropriate default stdio stream (USB or Bluetooth).
Now that USB is mostly working, we can enable it by default on SPIKE Essential and Prime hubs.
Member
|
Sounds very exciting! Let's discuss the API changes over some 🍵. |
This was referenced Jul 17, 2025
Merged
Member
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Well, I might have got a bit carried away with this. 😀
In addition to fixing the issue with USB stdout blocking forever when an app was not connected to the hub, I added a dynamic sys/std{in,out,err} to MicroPython.
Initially, we were considering following the MicroPython "dupterm" mechanism of connecting multiple streams in parallel for stdin/stdout. This would be fine as long as we only ever had one connection type at a time. But I don't think that is a reasonable expectation. And I think it would be very confusing to users that wanted to use multiple connections at the same time.
So they way this works is that Bluetooth and USB stdin/stdout are treated as two completely separate streams. When MicroPython starts, it will use a sensible default (what this means exactly is up for discussion). But both streams are always present at
hub.ble.ioandhub.usb.io.So for people that want to use both connections, they now have full control and can read and write data from either stream and know where it is coming/from going to. For example, you could use USB for stdio (print messages) and Bluetooth for remote control. I.e. you could add
sys.stdout = hub.usb.ioearly in the program to always print to USB.This requires
pbricksdevfrom themasterbranch for testing.I used this program to check that things didn't lock up waiting for print over USB when running without USB connection or disconnecting while running.